package edu.uts.reekie.designer.implementation.figures;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;

import org.eclipse.draw2d.*;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;


import edu.uts.reekie.designer.figures.ConnectionAnchorProvider;
import edu.uts.reekie.designer.figures.NameableFigure;

public class ViewExternalInterfaceFigure extends Figure implements NameableFigure, ConnectionAnchorProvider{
	
	private static final int CIRCLE_DIAMETER = 25;
	private static final int CIRCLE_HORIZONTAL_PAD = 4;
	private static final int CIRCLE_VERTICAL_PAD =2;
	private static final Dimension CIRCLE_SIZE = new Dimension(CIRCLE_DIAMETER+CIRCLE_HORIZONTAL_PAD, CIRCLE_DIAMETER+CIRCLE_VERTICAL_PAD);
	
	private Dimension textSize;
	
	private String name;
	
	
	public ViewExternalInterfaceFigure(){
		this("");
	}
	
	public ViewExternalInterfaceFigure(String name) {
		
		// set the font
		Font f = new Font(null,"Arial",10,SWT.NORMAL);
		setFont(f);
		
		setName(name);
		
		setLayoutManager(new StackLayout());
		
		// set the fg/bg colours
		setBackgroundColor(ColorConstants.black);
		setForegroundColor(ColorConstants.black);
		
	}
	
	public ConnectionAnchor getAnchor() {
		return new ViewExternalInterfaceAnchor(this);
	}
	
	class ViewExternalInterfaceAnchor extends AbstractConnectionAnchor {
		
		
		public ViewExternalInterfaceAnchor(ViewExternalInterfaceFigure owner){
			super(owner);
		}
		
		private Rectangle getCircleBounds() {
			Rectangle ownerBounds = getOwner().getBounds();
			Rectangle circleBounds = ownerBounds.getIntersection(new Rectangle(ownerBounds.x,ownerBounds.y,CIRCLE_DIAMETER,CIRCLE_DIAMETER));
			return circleBounds;
		}

		public Point getReferencePoint() {
			
			
			Point ref = getCircleBounds().getCenter();
			getOwner().translateToAbsolute(ref);
			return ref;
			
		}
		
		/**
		 * Returns a point on the ellipse (defined by the owner's bounding box) where the
		 * connection should be anchored.
		 * @see org.eclipse.draw2d.ConnectionAnchor#getLocation(Point)
		 */
		public Point getLocation(Point reference) {
			Rectangle r = Rectangle.SINGLETON;
			Rectangle circleBounds =  getCircleBounds();
			r.setBounds(circleBounds);
			
			r.translate(-1, -1);
			r.resize(1, 1);
			getOwner().translateToAbsolute(r);
			
			Point ref = r.getCenter().negate().translate(reference);
			
			if (ref.x == 0)
				return new Point(reference.x, (ref.y > 0) ? r.bottom() : r.y);
			if (ref.y == 0)
				return new Point((ref.x > 0) ? r.right() : r.x, reference.y);
			
			float dx = (ref.x > 0) ? 0.5f : -0.5f;
			float dy = (ref.y > 0) ? 0.5f : -0.5f;
			  
			// ref.x, ref.y, r.width, r.height != 0 => safe to proceed
			  
			float k = (float)(ref.y * r.width) / (ref.x * r.height);
			k = k * k;
			  
			return r.getCenter().translate((int)(r.width * dx / Math.sqrt(1 + k)),
			                                (int)(r.height * dy / Math.sqrt(1 + 1 / k)));
		}
		
	}
	
	
	public Dimension getPreferredSize(int wHint, int hHint) {
		Dimension size = CIRCLE_SIZE.getCopy();
		
		// expand the circle size horizontally by the text size
		if (textSize.height>size.height){
			size.expand(textSize.width, textSize.height - size.height);
		} else {
			size.expand(textSize.width,0);
		}
		return size;
	}
	
	Dimension getNameDimension() {
		TextUtilities tu = new TextUtilities();
		return tu.getTextExtents(name, getFont());
	}
	
	protected void paintFigure(Graphics g){
		
		Rectangle circleRect = getBounds().getCopy();
		Rectangle textRect = getBounds().getCopy();
		circleRect.setSize(CIRCLE_DIAMETER, CIRCLE_DIAMETER);

		//draw main area
		g.drawOval(circleRect);
		
		// draw the main text if it's available
		if (name==null || name.equalsIgnoreCase("")){
		} else {
			textRect.translate(CIRCLE_SIZE.width, 5);
			g.drawText(name,textRect.x,textRect.y);
		}
	}

	public String getName() {
		
		return name;
	}

	public void setName(String newName) {
		this.name = newName;	
		textSize = getNameDimension();
	}
	

	protected boolean useLocalCoordinates(){return false;}
	

}
